<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Target Name="_ComputeIlcCompileInputs"
          BeforeTargets="ComputeIlcCompileInputs"
          DependsOnTargets="$(IlcDynamicBuildPropertyDependencies)">
    <ItemGroup>
      <IlcReference Include="@(_ManagedResolvedAssembliesToPublish)" />
      <IlcSatelliteAssembly Include="@(_SatelliteAssembliesToPublish)" />
      <IlcSatelliteAssembly Include="@(IntermediateSatelliteAssembliesWithTargetPath)" />
    </ItemGroup>
  </Target>

  <!--
    This target hooks into the dotnet CLI publish pipeline. That pipeline has
    a target called ComputeFilesToPublish which produces the ItemGroup
    ResolvedFileToPublish based on the inputs of @(IntermediateAssembly)
    and @(ResolvedAssembliesToPublish). We modify those two item groups
    to control what gets published after NativeAOT optimizes the application.
  -->
  <Target Name="ComputeLinkedFilesToPublish"
          BeforeTargets="ComputeResolvedFilesToPublishList"
          DependsOnTargets="_ComputeAssembliesToCompileToNative;LinkNative">

    <ItemGroup>
      <_ResolvedCopyLocalPublishAssets Remove="@(_AssembliesToSkipPublish)" />
      <_ResolvedCopyLocalPublishAssets Include="@(_LinkedResolvedAssemblies)" />
      <_DebugSymbolsIntermediatePath Remove="@(_DebugSymbolsIntermediatePath)" />
    </ItemGroup>

    <ItemGroup>
      <_NativeIntermediateAssembly Include="@(IntermediateAssembly->'$(NativeOutputPath)%(Filename)$(NativeBinaryExt)')" />
      <IntermediateAssembly Remove="@(IntermediateAssembly)" />
      <IntermediateAssembly Include="@(_NativeIntermediateAssembly)" />
    </ItemGroup>
  </Target>

  <!--
    Filter the input publish file list selecting managed assemblies for compilation.
    Also produces _AssembliesToSkipPublish which chops out things from the publish
    pipeline we don't want to see in the output (native images, CoreCLR artifacts)
    until we get a proper AOT NetCore app package.
  -->
  <UsingTask TaskName="ComputeManagedAssembliesToCompileToNative" AssemblyFile="$(IlcBuildTasksPath)" />
  <Target Name="_ComputeAssembliesToCompileToNative" DependsOnTargets="$(IlcDynamicBuildPropertyDependencies)">

    <Warning Condition="Exists($(UserRuntimeConfig))" Text="The published project has a runtimeconfig.template.json that is not supported by PublishAot. Move the configuration to the project file using RuntimeHostConfigurationOption." />
    <!-- Fail with descriptive error message for common mistake. -->
    <Error Condition="$([MSBuild]::VersionLessThan('$(NETCoreSdkVersion)', '6.0.0'))" Text=".NET SDK 6+ is required for native compilation." />
    <Error Condition="$([MSBuild]::VersionLessThan('$(TargetFrameworkVersion)', '6.0'))" Text="For native compilation, the project needs to target .NET 6 or higher." />
    <Error Condition="'$(RuntimeIdentifier)' == ''"
      Text="RuntimeIdentifier is required for native compilation. Try running dotnet publish with the -r option value specified." />
    <Error Condition="'$(GeneratePackageOnBuild)' == 'true'" Text="GeneratePackageOnBuild is not supported for native compilation." />
    <Error Condition="'$(OutputType)' != 'Library' and '$(NativeLib)' != '' and '$(CustomNativeMain)' != 'true'" Text="NativeLib requires OutputType=Library." />
    <Warning Condition="'$(NativeLib)' != '' and '$(EventSourceSupport)' == 'true' and '$(_SuppressNativeLibEventSourceWarning)' != 'true'" Text="EventSource is not supported or recommended when compiling to a native library. Please go to https://github.com/dotnet/runtime/issues/91762 for more details." />

    <Error Condition="'$(PublishTrimmed)' == 'false'" Text="PublishTrimmed is implied by native compilation and cannot be disabled." />

    <Error Condition="'$(DynamicCodeSupport)' == 'true'" Text="DynamicCodeSupport property cannot be set to true with native compilation." />

    <!-- Fail with descriptive error message for common unsupported cases. -->
    <Error Condition="'$(DisableUnsupportedError)' != 'true' and '$(OS)' == 'Windows_NT' and '$(_targetOS)' != 'win'"
      Text="Cross-OS native compilation is not supported." />

    <Error Condition="'$(DisableUnsupportedError)' != 'true' and '$(OS)' != 'Windows_NT' and '$(_targetOS)' == 'win'"
      Text="Cross-OS native compilation is not supported." />

    <Error Condition="'$(DisableUnsupportedError)' != 'true' and '$(_targetArchitecture)' != 'x64' and '$(_targetArchitecture)' != 'arm64' and '$(_targetArchitecture)' != 'arm'"
      Text="Native compilation does not support targeting $(RuntimeIdentifier) yet." />

    <Error Condition="'$(DisableUnsupportedError)' != 'true' and !('$(_hostArchitecture)' == 'x64' or '$(_hostArchitecture)' == 'arm64' or '$(_hostArchitecture)' == 'arm')"
      Text="Native compilation can run on x64, arm64 and arm hosts only." />

    <Error Condition="'$(IlcHostPackagePath)' == '' and '$(RuntimePackagePath)' != '' and ('$(_hostArchitecture)' == 'x64' or '$(_hostArchitecture)' == 'arm64')"
      Text="Add a PackageReference for '$(_hostPackageName)' to allow cross-compilation for $(_targetArchitecture)" />

    <!-- NativeAOT runtime pack assemblies need to be defined to avoid the default CoreCLR implementations being set as compiler inputs -->
    <Error Condition="'@(PrivateSdkAssemblies)' == '' and '$(PublishAotUsingRuntimePack)' != 'true'" Text="The PrivateSdkAssemblies ItemGroup is required for _ComputeAssembliesToCompileToNative" />
    <Error Condition="'@(FrameworkAssemblies)' == '' and '$(PublishAotUsingRuntimePack)' != 'true'" Text="The FrameworkAssemblies ItemGroup is required for _ComputeAssembliesToCompileToNative" />

    <ComputeManagedAssembliesToCompileToNative
      Assemblies="@(_ResolvedCopyLocalPublishAssets)"
      DotNetAppHostExecutableName="$(_DotNetAppHostExecutableName)"
      DotNetHostFxrLibraryName="$(_DotNetHostFxrLibraryName)"
      DotNetHostPolicyLibraryName="$(_DotNetHostPolicyLibraryName)"
      SdkAssemblies="@(PrivateSdkAssemblies)"
      FrameworkAssemblies="@(FrameworkAssemblies)">

      <Output TaskParameter="ManagedAssemblies" ItemName="_ManagedResolvedAssembliesToPublish" />
      <Output TaskParameter="SatelliteAssemblies" ItemName="_SatelliteAssembliesToPublish" />
      <Output TaskParameter="AssembliesToSkipPublish" ItemName="_AssembliesToSkipPublish" />
    </ComputeManagedAssembliesToCompileToNative>

  </Target>

  <Target Name="CopyNativeBinary" AfterTargets="Publish">
    <!-- replace apphost with binary we generated during native compilation -->
    <Delete Files="$(PublishDir)\$(TargetName)$(NativeBinaryExt)" />
    <Copy SourceFiles="$(NativeOutputPath)$(TargetName)$(NativeBinaryExt)" DestinationFolder="$(PublishDir)" />
  </Target>

  <Target Name="_CopyAotSymbols" AfterTargets="Publish"
          Condition="'$(CopyOutputSymbolsToPublishDirectory)' == 'true'">
    <!-- dotnet CLI produces managed debug symbols, which we will delete and copy native symbols instead -->
    <Delete Files="$(PublishDir)\$(TargetName).pdb" />

    <PropertyGroup>
      <_symbolExt Condition="'$(OS)' == 'Windows_NT'">$(NativeSymbolExt)</_symbolExt>
      <_symbolExt Condition="'$(OS)' != 'Windows_NT'">$(NativeBinaryExt)$(NativeSymbolExt)</_symbolExt>
      <_symbolSourcePath>$(NativeOutputPath)$(TargetName)$(_symbolExt)</_symbolSourcePath>
      <_symbolTargetPath>$(PublishDir)\$(TargetName)$(_symbolExt)</_symbolTargetPath>
      <!-- If the symbol is a dSYM bundle, it's a folder not a file. -->
      <_symbolIsFile Condition="'$(NativeSymbolExt)' == '.dSYM'">false</_symbolIsFile>
      <_symbolIsFile Condition="'$(_symbolIsFile)' == ''">true</_symbolIsFile>
    </PropertyGroup>

    <ItemGroup>
      <_symbolRecursivePath Include="$(NativeOutputPath)$(TargetName)$(_symbolExt)/**/*" />
    </ItemGroup>

    <!-- replace native symbol file if it exists. On Mac, the symbol path may be a folder-->
    <Delete Files="$(_symbolTargetPath)" Condition="'$(_symbolIsFile)' == 'true' and Exists('$(_symbolTargetPath)')" />
    <Copy SourceFiles="$(_symbolSourcePath)" DestinationFolder="$(PublishDir)"
      Condition="'$(_symbolIsFile)' == 'true' and Exists('$(_symbolSourcePath)')" />

    <!-- Copy folder otherwise -->
    <RemoveDir Directories="$(_symbolTargetPath)" Condition="'$(_symbolIsFile)' == 'false' and Exists('$(_symbolTargetPath)')" />
    <Copy SourceFiles="@(_symbolRecursivePath)" DestinationFolder="$(_symbolTargetPath)/%(RecursiveDir)"
      Condition="'$(_symbolIsFile)' == 'false' and Exists('$(_symbolSourcePath)')" />
  </Target>

</Project>
